package xyz.lilei23.framework.core;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

/**
 * 委托者用于beanPostProcessor注入
 * @author jack
 * @date 31/07/2021 16:20
 * @version 1.0
 */
final class PostProcessorRegistrationDelegate {

	private PostProcessorRegistrationDelegate() {
	}

    /**
     * 获取beanPostProcessor并注册
     * @param beanFactory bean工厂
     */
    public static void registerBeanPostProcessors(BeanFactory beanFactory) {
        //拿到工程里面所有实现了BeanPostProcessor接口的类，获取到BeanDefinition的名称
        String[] postProcessorNames = beanFactory.getBeanNamesForType(BeanPostProcessor.class);
        List<BeanPostProcessor> orderedPostProcessors = new ArrayList<>();
        List<String> nonOrderedPostProcessorNames = new ArrayList<>();
        //提前实例化BeanPostProcessor类型的bean，然后bean进行排序
        for (String ppName : postProcessorNames) {
            if (beanFactory.isTypeMatch(ppName, Ordered.class)) {
                BeanPostProcessor postProcessor = (BeanPostProcessor) beanFactory.getBean(BeanPostProcessor.class, ppName);
                orderedPostProcessors.add(postProcessor);
            } else {
                nonOrderedPostProcessorNames.add(ppName);
            }
        }
        sortPostProcessors(orderedPostProcessors);
        registerBeanPostProcessors(beanFactory, orderedPostProcessors);
        List<BeanPostProcessor> nonOrderedPostProcessors = new ArrayList<>();
        for (String ppName : nonOrderedPostProcessorNames) {
            BeanPostProcessor postProcessor = (BeanPostProcessor) beanFactory.getBean(BeanPostProcessor.class, ppName);
            nonOrderedPostProcessors.add(postProcessor);
        }
        registerBeanPostProcessors(beanFactory, nonOrderedPostProcessors);
    }

    private static void sortPostProcessors(List<BeanPostProcessor> orderedPostProcessors) {
        orderedPostProcessors.sort(Comparator.comparingInt(o -> ((Ordered) o).getOrder()));
    }

    private static void registerBeanPostProcessors(
            BeanFactory beanFactory, List<BeanPostProcessor> postProcessors) {
        for (BeanPostProcessor postProcessor : postProcessors) {
            beanFactory.addBeanPostProcessor(postProcessor);
        }
    }

}
